/**
 * WebSocket连接管理器
 * ===================
 * 
 * 负责WebSocket连接的建立、维护、重连和消息处理
 * 支持自动重连、心跳检测、订阅管理等功能
 */

export interface WebSocketManagerConfig {
  url: string;
  reconnectInterval?: number;
  maxReconnectAttempts?: number;
  heartbeatInterval?: number;
  timeout?: number;
}

export interface WebSocketMessage {
  type: string;
  data: any;
  timestamp: number;
  request_id?: string;
}

export interface WebSocketCallbacks {
  onConnect?: () => void;
  onDisconnect?: (code: number, reason: string) => void;
  onMessage?: (message: WebSocketMessage) => void;
  onError?: (error: Event) => void;
  onReconnect?: (attempt: number) => void;
  onReconnectFailed?: () => void;
}

export enum WebSocketState {
  CONNECTING = 'connecting',
  CONNECTED = 'connected',
  DISCONNECTING = 'disconnecting',
  DISCONNECTED = 'disconnected',
  RECONNECTING = 'reconnecting'
}

export class WebSocketManager {
  private ws: WebSocket | null = null;
  private config: Required<WebSocketManagerConfig>;
  private callbacks: WebSocketCallbacks;
  private state: WebSocketState = WebSocketState.DISCONNECTED;
  private reconnectAttempts = 0;
  private reconnectTimer: NodeJS.Timeout | null = null;
  private heartbeatTimer: NodeJS.Timeout | null = null;
  private subscriptions = new Set<string>();
  private messageQueue: WebSocketMessage[] = [];
  private isManualDisconnect = false;

  constructor(config: WebSocketManagerConfig, callbacks: WebSocketCallbacks = {}) {
    this.config = {
      url: config.url,
      reconnectInterval: config.reconnectInterval ?? 5000,
      maxReconnectAttempts: config.maxReconnectAttempts ?? 10,
      heartbeatInterval: config.heartbeatInterval ?? 30000,
      timeout: config.timeout ?? 60000
    };
    this.callbacks = callbacks;
  }

  /**
   * 连接到WebSocket服务器
   */
  async connect(): Promise<void> {
    if (this.state === WebSocketState.CONNECTED || this.state === WebSocketState.CONNECTING) {
      console.warn('WebSocket already connected or connecting');
      return;
    }

    this.state = WebSocketState.CONNECTING;
    this.isManualDisconnect = false;

    try {
      this.ws = new WebSocket(this.config.url);
      this.setupEventHandlers();
    } catch (error) {
      console.error('Failed to create WebSocket connection:', error);
      this.state = WebSocketState.DISCONNECTED;
      this.callbacks.onError?.(error as Event);
      throw error;
    }
  }

  /**
   * 断开WebSocket连接
   */
  async disconnect(): Promise<void> {
    this.isManualDisconnect = true;
    this.state = WebSocketState.DISCONNECTING;

    // 清除定时器
    this.clearTimers();

    if (this.ws) {
      this.ws.close(1000, 'Manual disconnect');
      this.ws = null;
    }

    this.state = WebSocketState.DISCONNECTED;
    this.callbacks.onDisconnect?.(1000, 'Manual disconnect');
  }

  /**
   * 发送消息
   */
  send(message: Partial<WebSocketMessage>): boolean {
    if (this.state !== WebSocketState.CONNECTED || !this.ws) {
      console.warn('WebSocket not connected, queueing message');
      this.messageQueue.push(message as WebSocketMessage);
      return false;
    }

    try {
      const fullMessage: WebSocketMessage = {
        type: message.type || 'message',
        data: message.data || {},
        timestamp: Date.now(),
        request_id: message.request_id
      };

      this.ws.send(JSON.stringify(fullMessage));
      return true;
    } catch (error) {
      console.error('Failed to send WebSocket message:', error);
      return false;
    }
  }

  /**
   * 订阅数据
   */
  subscribe(symbols: string[]): boolean {
    const newSymbols = symbols.filter(symbol => !this.subscriptions.has(symbol));
    
    if (newSymbols.length === 0) {
      return true;
    }

    // 添加到本地订阅列表
    newSymbols.forEach(symbol => this.subscriptions.add(symbol));

    // 发送订阅消息
    return this.send({
      type: 'subscribe',
      data: { symbols: newSymbols }
    });
  }

  /**
   * 取消订阅
   */
  unsubscribe(symbols: string[]): boolean {
    const existingSymbols = symbols.filter(symbol => this.subscriptions.has(symbol));
    
    if (existingSymbols.length === 0) {
      return true;
    }

    // 从本地订阅列表移除
    existingSymbols.forEach(symbol => this.subscriptions.delete(symbol));

    // 发送取消订阅消息
    return this.send({
      type: 'unsubscribe',
      data: { symbols: existingSymbols }
    });
  }

  /**
   * 获取当前状态
   */
  getState(): WebSocketState {
    return this.state;
  }

  /**
   * 是否已连接
   */
  isConnected(): boolean {
    return this.state === WebSocketState.CONNECTED;
  }

  /**
   * 获取订阅列表
   */
  getSubscriptions(): string[] {
    return Array.from(this.subscriptions);
  }

  /**
   * 设置事件处理器
   */
  private setupEventHandlers(): void {
    if (!this.ws) return;

    this.ws.onopen = () => {
      console.log('WebSocket connected');
      this.state = WebSocketState.CONNECTED;
      this.reconnectAttempts = 0;
      this.clearTimers();
      this.startHeartbeat();
      this.processMessageQueue();
      this.callbacks.onConnect?.();
    };

    this.ws.onclose = (event) => {
      console.log('WebSocket disconnected:', event.code, event.reason);
      this.state = WebSocketState.DISCONNECTED;
      this.clearTimers();
      this.callbacks.onDisconnect?.(event.code, event.reason);

      // 如果不是手动断开，尝试重连
      if (!this.isManualDisconnect && this.reconnectAttempts < this.config.maxReconnectAttempts) {
        this.scheduleReconnect();
      } else if (this.reconnectAttempts >= this.config.maxReconnectAttempts) {
        console.error('Max reconnection attempts reached');
        this.callbacks.onReconnectFailed?.();
      }
    };

    this.ws.onerror = (error) => {
      console.error('WebSocket error:', error);
      this.callbacks.onError?.(error);
    };

    this.ws.onmessage = (event) => {
      try {
        const message: WebSocketMessage = JSON.parse(event.data);
        this.handleMessage(message);
      } catch (error) {
        console.error('Failed to parse WebSocket message:', error);
      }
    };
  }

  /**
   * 处理接收到的消息
   */
  private handleMessage(message: WebSocketMessage): void {
    switch (message.type) {
      case 'connect':
        console.log('WebSocket connection confirmed:', message.data);
        break;
      
      case 'subscribe':
        console.log('Subscription confirmed:', message.data);
        break;
      
      case 'unsubscribe':
        console.log('Unsubscription confirmed:', message.data);
        break;
      
      case 'data':
        // 实时数据推送
        this.callbacks.onMessage?.(message);
        break;
      
      case 'pong':
        // 心跳响应
        console.debug('Received pong');
        break;
      
      case 'error':
        console.error('WebSocket server error:', message.data);
        break;
      
      default:
        console.log('Unknown message type:', message.type);
        this.callbacks.onMessage?.(message);
    }
  }

  /**
   * 启动心跳检测
   */
  private startHeartbeat(): void {
    this.heartbeatTimer = setInterval(() => {
      if (this.state === WebSocketState.CONNECTED) {
        this.send({ type: 'ping' });
      }
    }, this.config.heartbeatInterval);
  }

  /**
   * 安排重连
   */
  private scheduleReconnect(): void {
    if (this.reconnectTimer) return;

    this.state = WebSocketState.RECONNECTING;
    this.reconnectAttempts++;

    console.log(`Scheduling reconnect attempt ${this.reconnectAttempts} in ${this.config.reconnectInterval}ms`);
    
    this.reconnectTimer = setTimeout(() => {
      this.reconnectTimer = null;
      this.callbacks.onReconnect?.(this.reconnectAttempts);
      this.connect().catch(error => {
        console.error('Reconnection failed:', error);
      });
    }, this.config.reconnectInterval);
  }

  /**
   * 处理消息队列
   */
  private processMessageQueue(): void {
    while (this.messageQueue.length > 0 && this.state === WebSocketState.CONNECTED) {
      const message = this.messageQueue.shift();
      if (message) {
        this.send(message);
      }
    }
  }

  /**
   * 清除所有定时器
   */
  private clearTimers(): void {
    if (this.reconnectTimer) {
      clearTimeout(this.reconnectTimer);
      this.reconnectTimer = null;
    }
    
    if (this.heartbeatTimer) {
      clearInterval(this.heartbeatTimer);
      this.heartbeatTimer = null;
    }
  }

  /**
   * 销毁管理器
   */
  destroy(): void {
    this.clearTimers();
    this.disconnect();
    this.subscriptions.clear();
    this.messageQueue = [];
  }
}
